{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "68ca2f32-f5a1-4320-a614-3a38fc93f13e",
   "metadata": {},
   "source": [
    "# Understanding Custom Space\n",
    "\n",
    "CustomSpace is the tool to incorporate vectors created outside the Superlinked system."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "311a29fe-dc05-4e19-8b0e-5c7c199bb27d",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install superlinked==37.5.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "988afce9-46c5-4d1a-b3cc-1a76c2806dc1",
   "metadata": {},
   "outputs": [],
   "source": [
    "from superlinked import framework as sl"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dc42deba-9ef9-4c54-9441-6b7d045629ad",
   "metadata": {},
   "source": [
    "## Creating a custom space\n",
    "\n",
    "To use pre-created custom vectors in Superlinked:\n",
    "* create a schema (just like in any other case) with a `FloatList` type `SchemaField`,\n",
    "* create a `CustomSpace` based on that field. You only need to set the length of the `FloatList`, meaning the number of scalars your vectors (referring to 1 entity) consist of,\n",
    "* working with Superlinked, vectors often need to be aggregated (see [event effects](event_effects.ipynb) for example) or normalized.\n",
    "* During aggregation vectors are summed up elementwise, and normalized using L2 norm of the vector to achieve unit vector length when needed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d4f6cca4-90c8-4029-ab6a-635a20b7f236",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Product(sl.Schema):\n",
    "    id: sl.IdField\n",
    "    sales_history: sl.FloatList  # we need to supply vectors using this SchemaFieldType\n",
    "\n",
    "\n",
    "product = Product()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "89412b45-7069-4970-a24f-a4c4f5eda6a7",
   "metadata": {},
   "outputs": [],
   "source": [
    "sales_history_space = sl.CustomSpace(\n",
    "    vector=product.sales_history,\n",
    "    length=3,\n",
    ")\n",
    "product_index = sl.Index(sales_history_space)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "acedaea4-56cc-4229-a1d6-36f225c8f007",
   "metadata": {},
   "outputs": [],
   "source": [
    "source: sl.InMemorySource = sl.InMemorySource(product)\n",
    "executor = sl.InMemoryExecutor(sources=[source], indices=[product_index])\n",
    "app = executor.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "24f2cb81-ace2-48de-bc78-1ab0fd5bffd8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# FloatList can be parsed from list or np.array of floats or ints\n",
    "source.put(\n",
    "    [\n",
    "        {\"id\": \"product-1\", \"sales_history\": [1.0, 0.0, 0.0]},\n",
    "        {\"id\": \"product-2\", \"sales_history\": [0.0, 0.8, 0.2]},\n",
    "        {\"id\": \"product-3\", \"sales_history\": [0.1, 0.1, 0.8]},\n",
    "    ]\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbb435fb-b513-458b-8cba-06dd7861585c",
   "metadata": {},
   "source": [
    "At query-time, we can search with any vector that has the correct length, this is demonstrated here by making all of the 3 products be the first result once."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "3a9d6813-52f6-40ab-810d-430f8b1d2561",
   "metadata": {},
   "outputs": [],
   "source": [
    "sales_history_query = (\n",
    "    sl.Query(product_index).find(product).similar(sales_history_space, sl.Param(\"sales_history\")).select_all()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "80f325e0-3feb-4d83-9be6-7c5128490728",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sales_history</th>\n",
       "      <th>id</th>\n",
       "      <th>similarity_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[1.0, 0.0, 0.0]</td>\n",
       "      <td>product-1</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[0.1, 0.1, 0.8]</td>\n",
       "      <td>product-3</td>\n",
       "      <td>0.123091</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[0.0, 0.8, 0.2]</td>\n",
       "      <td>product-2</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     sales_history         id  similarity_score\n",
       "0  [1.0, 0.0, 0.0]  product-1          1.000000\n",
       "1  [0.1, 0.1, 0.8]  product-3          0.123091\n",
       "2  [0.0, 0.8, 0.2]  product-2          0.000000"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = app.query(sales_history_query, sales_history=[1.0, 0.0, 0.0])\n",
    "sl.PandasConverter.to_pandas(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "12aab4ed-4374-4a7b-a42f-0bd597bb52f6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sales_history</th>\n",
       "      <th>id</th>\n",
       "      <th>similarity_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[0.0, 0.8, 0.2]</td>\n",
       "      <td>product-2</td>\n",
       "      <td>0.970143</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[0.1, 0.1, 0.8]</td>\n",
       "      <td>product-3</td>\n",
       "      <td>0.123091</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[1.0, 0.0, 0.0]</td>\n",
       "      <td>product-1</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     sales_history         id  similarity_score\n",
       "0  [0.0, 0.8, 0.2]  product-2          0.970143\n",
       "1  [0.1, 0.1, 0.8]  product-3          0.123091\n",
       "2  [1.0, 0.0, 0.0]  product-1          0.000000"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = app.query(sales_history_query, sales_history=[0.0, 1.0, 0.0])\n",
    "sl.PandasConverter.to_pandas(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "45930bf9-d2f5-468f-92c6-e5a00b4f1b42",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sales_history</th>\n",
       "      <th>id</th>\n",
       "      <th>similarity_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[0.1, 0.1, 0.8]</td>\n",
       "      <td>product-3</td>\n",
       "      <td>0.984732</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[0.0, 0.8, 0.2]</td>\n",
       "      <td>product-2</td>\n",
       "      <td>0.242536</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[1.0, 0.0, 0.0]</td>\n",
       "      <td>product-1</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     sales_history         id  similarity_score\n",
       "0  [0.1, 0.1, 0.8]  product-3          0.984732\n",
       "1  [0.0, 0.8, 0.2]  product-2          0.242536\n",
       "2  [1.0, 0.0, 0.0]  product-1          0.000000"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = app.query(sales_history_query, sales_history=[0.0, 0.0, 1.0])\n",
    "sl.PandasConverter.to_pandas(result)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "superlinked-py3.11",
   "language": "python",
   "name": "superlinked-py3.11"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
